package com.infore.dataAudit.service.audit.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.infore.dataAudit.dto.HourData;
import com.infore.dataAudit.dto.Project;
import com.infore.dataAudit.dto.SpanDrift;
import com.infore.dataAudit.dto.ZeroDrift;
import com.infore.dataAudit.entity.TDataAudit;
import com.infore.dataAudit.enums.AuditStatus;
import com.infore.dataAudit.enums.SystemDataStatus;
import com.infore.dataAudit.repository.ITDataAuditRepository;
import com.infore.dataAudit.service.EntityMapService;
import com.infore.dataAudit.service.audit.AutomaticAuditService;
import com.infore.dataAudit.service.audit.IDataAuditService;
import com.infore.dataAudit.util.Constants;
import com.infore.dataAudit.util.ResultEntity;
import com.infore.dataAudit.vo.OriginalData;

@Service("automaticAuditService")
public class AutomaticAuditServiceImpl implements AutomaticAuditService {

    @Autowired
    private ITDataAuditRepository dataAuditRepository;
    @Autowired
    private EntityMapService entityMapService;
    @Autowired
    private IDataAuditService dataAuditService;
    
    private Map<String, Object> param;
    
    private String flowId;

    @Override
    public ResultEntity startAutomaticAudit(Map<String, Object> params) {
        this.param = params;
        System.out.println("-------开始自动审核------------");
        // 获取此监测站 这天的监测数据
        String mn = (String) params.get("stationMn");
        String time = (String) params.get("stationTime"); // 某天 yyyy-MM-dd
        this.flowId = (String) params.get("flowId");
        
        System.out.println("流程实例id--: " + this.flowId);
        
        List<OriginalData> oriDatas = this.getOriginalDatas(time, mn);

        System.out.println("1、无效数据判定");
        this.judgeInvalidData(oriDatas, mn);

        System.out.println("2、存疑数据判定");
        this.judgeDoubtData(oriDatas);

        System.out.println("3、完成审核 录入有效数据");
        int size = this.saveValidData(oriDatas);
        System.out.println("有效数据数量: "+ size);
        return null;
    }

   

    /**
     * 获取远程的原始数据 进行自动审核 模拟数据 假的
     * 
     * @author 蔡永顺
     * @return List<OriginalData>
     * @param time
     * @param mn
     * @return
     * @date 2019年4月23日上午9:05:15
     */
    private List<OriginalData> getOriginalDatas(String time, String mn) {
        Map<String, List<HourData>> mapHourData = Constants.getStationHourData();
        List<HourData> hourDatas = mapHourData.get(mn);
        List<OriginalData> oriDatas = new ArrayList<>();
        List<Project> projectInfos = dataAuditService.projectInfoAllAudit(null);
        Map<String, Project> mapProj = new HashMap<>();
        for (Project project : projectInfos) {
            mapProj.put(project.getProjectCode(), project);
        }
        entityMapService.hourData2OriginalData(hourDatas, oriDatas, mapProj);
        return oriDatas;
    }
    
    /**
     * 无效数据判定
     * 
     * @author 蔡永顺
     * @param oriDatas
     * @return boolean
     * @return
     * @date 2019年4月3日上午10:04:39
     */
    private boolean judgeInvalidData(List<OriginalData> oriDatas, String mn) {
        // 1、获取此时间点的质控数据 判定质控是否合格
        //
        //站点的跨度数据
        List<SpanDrift> spanDridtDatas = Constants.getStationSpanDrift().get(mn);
        this.judgeSpanDridtDatas(spanDridtDatas, oriDatas);
        //站点的零点数据
        List<ZeroDrift> zeroDrifttDatas = Constants.getStationZeroDrift().get(mn);
        this.judgeZeroDridtDatas(zeroDrifttDatas, oriDatas);
        // 水站维护测试时间段内产生的数据
        this.judgeMaintainTestData(oriDatas);
        // 水质自动分析仪出现故障产生的数据
        // 质控
        return true;
    }
    
    /**
     * 零点质控数据判定 是否合格
     * 
     * @author 蔡永顺
     * @return void
     * @param zeroDrifttDatas
     * @param oriDatas
     * @date 2019年5月31日下午3:22:05
     */
    private void judgeZeroDridtDatas(List<ZeroDrift> zeroDrifttDatas, List<OriginalData> oriDatas) {
        if(zeroDrifttDatas == null) {
            System.out.println("此监测站无跨度零点数据-------");
            return;
        }
        //因子跨度质控无效集合Map
        Map<String, List<ZeroDrift>> indexMap = new HashMap<>();
        for (ZeroDrift spanDrift : zeroDrifttDatas) {
            String code = spanDrift.getIndexCode();
            String qualification = spanDrift.getQualification();
            String lastQualification = spanDrift.getLastQualification();
            if(Constants.INQUALIFICATION.equals(qualification) ||
                    Constants.INQUALIFICATION.equals(lastQualification)) {
                if(indexMap.get(code) == null) {
                    indexMap.put(code, new ArrayList<>());
                }
                indexMap.get(code).add(spanDrift);
            }
        }
        Iterator<OriginalData> it = oriDatas.iterator();
        List<ZeroDrift> list = null;
        OriginalData originalData = null;
        for (String code : indexMap.keySet()) {
            list = indexMap.get(code);
            if(list.size() >= 2) {
                while (it.hasNext()) {
                    originalData = it.next();
                    if(code.equals(originalData.getProjId())) {
                        this.setInvalidData(it, originalData, Constants.QUALIFICATION_NOT_PASS);
                    }
                }
            }
        }
        
    }

    /**
     * 跨度数据判定 是否合格
     * 
     * @author 蔡永顺
     * @return void
     * @param spanDridtDatas
     * @param oriDatas
     * @date 2019年5月31日下午3:03:55
     */
    private void judgeSpanDridtDatas(List<SpanDrift> spanDridtDatas, List<OriginalData> oriDatas) {
        if(spanDridtDatas == null) {
            System.out.println("此监测站无跨度核查数据-------");
            return;
        }
        //因子跨度质控无效集合Map
        Map<String, List<SpanDrift>> indexMap = new HashMap<>();
        for (SpanDrift spanDrift : spanDridtDatas) {
            String code = spanDrift.getIndexCode();
            String qualification = spanDrift.getQualification();
            String lastQualification = spanDrift.getLastQualification();
            if(Constants.INQUALIFICATION.equals(qualification) ||
                    Constants.INQUALIFICATION.equals(lastQualification)) {
                if(indexMap.get(code) == null) {
                    indexMap.put(code, new ArrayList<>());
                }
                indexMap.get(code).add(spanDrift);
            }
        }
        Iterator<OriginalData> it = oriDatas.iterator();
        List<SpanDrift> list = null;
        OriginalData originalData = null;
        for (String code : indexMap.keySet()) {
            list = indexMap.get(code);
            if(list.size() >= 2) {
                while (it.hasNext()) {
                    originalData = it.next();
                    if(code.equals(originalData.getProjId())) {
                        this.setInvalidData(it, originalData, Constants.QUALIFICATION_NOT_PASS);
                    }
                }
            }
        }
        
    }



    /**
     * 存疑数据判定
     * 
     * 
     * @author 蔡永顺
     * @param oriDatas 
     * @return boolean
     * @return
     * @date 2019年4月3日上午9:57:33
     */
    private boolean judgeDoubtData(List<OriginalData> oriDatas) {
        // 1、0值判断
        System.out.println("0值开始= "+oriDatas.size());
        this.judgeDoubtDataZero(oriDatas);
        System.out.println("0值结束= "+oriDatas.size());
        //2、检出限判断
        this.judgeDoubtDataOverLimit(oriDatas);
        //3、超三类水 判断
        this.judgeDoubtDataWQ(oriDatas);
        //4、监测数据突然变大、突然变小、连续不变
        this.judgeDoubtDataConChange(oriDatas);
        
        //5、当监测项目的关键状态值（消解温度、消解时长、显色温度等）不在合理范围。
        
        //6、数值间逻辑关系不符合要求。
        
        return true;
    }
    
    /**
     * 0值判断
     * 
     * @author 蔡永顺
     * @return void
     * @param oriDatas
     * @date 2019年4月23日下午5:47:59
     */
    private void judgeDoubtDataZero(List<OriginalData> oriDatas) {
        OriginalData originalData = null;
        Iterator<OriginalData> it = oriDatas.iterator();
        while (it.hasNext()) {
            originalData = it.next();
            if(originalData.getProjValue() == 0) {
                this.setDoubtData(it, originalData, "0值", true);
            };
            
        }
       
    }
    
    /**
     * 是否超出检出限 判断
     * 
     * @author 蔡永顺
     * @return void
     * @param oriDatas
     * @date 2019年4月23日下午5:47:59
     */
    private void judgeDoubtDataOverLimit(List<OriginalData> oriDatas) {
        OriginalData originalData = null;
        Iterator<OriginalData> it = oriDatas.iterator();
        while (it.hasNext()) {
            originalData = it.next();
            if(SystemDataStatus.T.getKey().equals(originalData.getStatus())) {
                this.setDoubtData(it, originalData, SystemDataStatus.T.getValue(), true);
            }else if(SystemDataStatus.L.getKey().equals(originalData.getStatus())) {
                this.setDoubtData(it, originalData, SystemDataStatus.L.getValue(), true);
            }
        }
    }
    
    /**
     * 水质等级超三级 三类值判断
     * 
     * @author 蔡永顺
     * @return void
     * @param oriDatas
     * @date 2019年4月23日下午5:47:59
     */
    private void judgeDoubtDataWQ(List<OriginalData> oriDatas) {
        OriginalData originalData = null;
        Iterator<OriginalData> it = oriDatas.iterator();
        while (it.hasNext()) {
            originalData = it.next();
            if(originalData.getWaterQality() > 3) {
                this.setDoubtData(it, originalData, "超Ⅲ类标准限制", true);
            }
        }
    }
    
    /**
     * 数值连续不变 突然变大 变小
     * 初始默认为4倍
     * @author 蔡永顺
     * @return void
     * @param oriDatas
     * @date 2019年4月23日下午6:17:12
     */
    private void judgeDoubtDataConChange(List<OriginalData> oriDatas) {
       // String oldProjId = "";
        double oldValue = 0;
        Map<String,Object> map = null;
        Map<String,Map<String,Object>> projMaps = new HashMap<>();
        OriginalData originalData = null;
        Iterator<OriginalData> it = oriDatas.iterator();
        while (it.hasNext()) {
            originalData = it.next();
            String projId = originalData.getProjId();
            double value = originalData.getProjValue();
            if(projMaps.get(projId) == null) {
                map = new HashMap<>();
                map.put("value", value);
                map.put("num", 1);
                projMaps.put(projId, map);
            }else {
                map = projMaps.get(projId);
                oldValue = (double) map.get("value"); 
                int num = (int) map.get("num");
                if(oldValue == value) {
                    num ++;
                    map.put("num", num);
                    //出现过5次 就判断为连续不变
                    if(num > 4) {
                        this.setDoubtData(it, originalData, "连续不变", false);  
                    }
                }else {
                    if(value > oldValue * 4)
                        this.setDoubtData(it, originalData, "突然变大", false);  
                    if(value < oldValue / 4)
                        this.setDoubtData(it, originalData, "突然变小", false); 
                    map.put("value", value);
                    map.put("num", 1);
                }
            }
        }
    }
    
    // 判定 水站维护测试时间段内产生的数据
    private boolean judgeMaintainTestData(List<OriginalData> oriDatas) {
        OriginalData originalData = null;
        Iterator<OriginalData> it = oriDatas.iterator();
        while (it.hasNext()) {
            originalData = it.next();
          //设备故障期间的数据 判定为无效
            if(SystemDataStatus.D.getKey().equals(originalData.getStatus())) {
                this.setInvalidData(it, originalData,
                        SystemDataStatus.getEnumByKey(originalData.getStatus())
                            .getValue());
            }
        }
        return false;
    }
    
    /**
     * 设置无效数据
     * 直接存储审核数据 移除此原始数据 取消审核判定
     * @author 蔡永顺
     * @return void
     * @param it
     * @param originalData
     * @param string
     * @date 2019年4月23日下午4:44:18
     */
    private void setInvalidData(Iterator<OriginalData> it, OriginalData originalData, String message) {
        TDataAudit dataAudit = entityMapService.originalData2TDataAudit(originalData);
        dataAudit.setFlowInstanceId(flowId);
        dataAudit.setXtAudit(AuditStatus.INVALIDE.getStatusCode());
        dataAudit.setXtAuditDesc(message);
        //存储
        dataAuditRepository.saveAndFlush(dataAudit);
        //移除 不做下次审核判定
        it.remove();
    }
    
    /**
     * 设置存疑数据
     * 直接存储审核数据 移除此原始数据 取消再次审核判定
     * 默认移除
     * @author 蔡永顺
     * @return void
     * @param it
     * @param originalData
     * @param message
     * @date 2019年4月23日下午5:49:50
     */
    private void setDoubtData(Iterator<OriginalData> it, OriginalData originalData, 
            String message, boolean isRemove) {
        TDataAudit dataAudit = entityMapService.originalData2TDataAudit(originalData);
        dataAudit.setFlowInstanceId(flowId);
        dataAudit.setXtAudit(AuditStatus.DOUBT.getStatusCode());
        dataAudit.setXtAuditDesc(message);
        //存储
        dataAuditRepository.saveAndFlush(dataAudit);
        //移除 不做下次审核判定
        if(isRemove) {
            it.remove();
        }
    }
    
    /**
     * 有效数据 存储
     * 
     * @author 蔡永顺
     * @return int
     * @param oriDatas
     * @return
     * @date 2019年4月24日上午10:02:11
     */
    private int saveValidData(List<OriginalData> oriDatas) {
        System.out.println(flowId+ " =流程实例id");
        List<TDataAudit> list = entityMapService.originalData2TDataAudit(oriDatas, flowId);
        //存储
        return dataAuditRepository.saveAll(list).size();
    }

}
